#pragma once

// 异步工作器(写缓冲区，交换缓冲区)

#include "buffer.hpp"
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <memory>

namespace mylog
{
    // 回调函数——工作线程(消费)
    using Functor = std::function<void(Buffer &)>;
    // 工作器类型
    enum AsyncLooperType
    {
        ASYNC_SAFE,  // 安全模式，空间满时阻塞
        ASYNC_UNSAFE // 极限测试模式，空间满时扩容
    };
    //异步工作器
    class AsyncLooper
    {
    public:
        using ptr = std::shared_ptr<AsyncLooper>;
        // 构造函数
        AsyncLooper(const Functor &cb, const AsyncLooperType &looper_type = AsyncLooperType::ASYNC_SAFE)
            : _stop(false),
              _type(looper_type),
              _thread(std::thread(&AsyncLooper::threadEntry, this)),
              _callback(cb)
        {}

        // 析构函数
        ~AsyncLooper()
        {
            stop();
        }
        // 停止异步工作器
        void stop()
        {
            // 将停止标记置真
            _stop = true;
            // 唤醒所有工作线程
            _cond_con.notify_all();
            // 等待工作线程结束
            _thread.join();
        }
        // 往生产缓冲区里写数据
        void push(const char *data, size_t len)
        {
            // 先加锁
            std::unique_lock<std::mutex> lock(_mutex);
            // 安全模式下才唤醒,缓冲区可写才唤醒
            if (_type == AsyncLooperType::ASYNC_SAFE)
                _cond_pro.wait(lock, [&]()
                               { return _pro_buf.writeAbleSize() >= len; });
            // 能够走下来，说明生产缓冲区可以写入
            _pro_buf.push(data, len);
            // 写入数据成功，唤醒工作线程
            _cond_con.notify_one();
        }

    private:
        // 工作线程入口函数
        void threadEntry()
        {
            while (1)
            {
                // 框出局部空间，只要交换缓冲区时加锁就好
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    //退出标志被设置，且生产缓冲区为空才退出，防止生产缓冲区还有数据，但_stop先被设置，导致数据未处理
                    if(_stop && _pro_buf.empty())
                        break;
                    // 异步工作器停止或消费缓冲区不为空时才唤醒
                    _cond_con.wait(lock, [&]()
                                   { return _stop || !_pro_buf.empty(); });
                    _con_buf.swap(_pro_buf); // 交换缓冲区
                    //安全模式下才唤醒
                    if (_type == AsyncLooperType::ASYNC_SAFE)
                        _cond_pro.notify_all();// 唤醒生产缓冲区
                }
                // 执行回调函数
                _callback(_con_buf);
                // 重置消费缓冲区
                _con_buf.reset();
            }
        }

    private:
        Functor _callback; // 具体对缓冲区数据进行处理的回调函数
    private:
        AsyncLooperType _type;   // 工作器类型
        std::atomic<bool> _stop; // 工作器停止标志
        Buffer _pro_buf;         // 生产缓冲区
        Buffer _con_buf;         // 消费缓冲区
        std::mutex _mutex;
        std::condition_variable _cond_pro; // 生产条件变量
        std::condition_variable _cond_con; // 消费条件变量
        std::thread _thread;               // 异步工作器对应的工作线程
    };
}